﻿using System;
using System.Collections;
using System.IO;

using log4net.Core;
using log4net.Layout.Pattern;
using log4net.Util;
using log4net.Layout;
using Clannan.Log4Net;
namespace Clannan.Log4Net
{
    public class CustomLayout2 : log4net.Layout.PatternLayout
    {
        public CustomLayout2()
        {
            this.AddConverter("Message", typeof(MessagePatternConverter));
            this.AddConverter("Source", typeof(SourcePatternConverter));
            this.AddConverter("Form", typeof(FormPatternConverter));
            this.AddConverter("QueryString", typeof(QueryStringPatternConverter));
            this.AddConverter("TargetSite", typeof(TargetSitePatternConverter));
            this.AddConverter("UserName", typeof(UserNamePatternConverter));
            this.AddConverter("StackTrace", typeof(StackTracePatternConverter));
            this.AddConverter("Solve", typeof(SolvePatternConverter));
        }
    }
    /// <summary>
    /// A flexible layout configurable with pattern string.
    /// </summary>
    /// <remarks>
    /// <para>
    /// The goal of this class is to <see cref="PatternLayout.Format"/> a 
    /// <see cref="LoggingEvent"/> as a string. The results
    /// depend on the <i>conversion pattern</i>.
    /// </para>
    /// <para>
    /// The conversion pattern is closely related to the conversion
    /// pattern of the printf function in C. A conversion pattern is
    /// composed of literal text and format control expressions called
    /// <i>conversion specifiers</i>.
    /// </para>
    /// <para>
    /// <i>You are free to insert any literal text within the conversion
    /// pattern.</i>
    /// </para>
    /// <para>
    /// Each conversion specifier starts with a percent sign (%) and is
    /// followed by optional <i>format modifiers</i> and a <i>conversion
    /// pattern name</i>. The conversion pattern name specifies the type of
    /// data, e.g. logger, level, date, thread name. The format
    /// modifiers control such things as field width, padding, left and
    /// right justification. The following is a simple example.
    /// </para>
    /// <para>
    /// Let the conversion pattern be <b>"%-5level [%thread]: %message%newline"</b> and assume
    /// that the log4net environment was set to use a PatternLayout. Then the
    /// statements
    /// </para>
    /// <code lang="C#">
    /// ILog log = LogManager.GetLogger(typeof(TestApp));
    /// log.Debug("Message 1");
    /// log.Warn("Message 2");   
    /// </code>
    /// <para>would yield the output</para>
    /// <code>
    /// DEBUG [main]: Message 1
    /// WARN  [main]: Message 2  
    /// </code>
    /// <para>
    /// Note that there is no explicit separator between text and
    /// conversion specifiers. The pattern parser knows when it has reached
    /// the end of a conversion specifier when it reads a conversion
    /// character. In the example above the conversion specifier
    /// <b>%-5level</b> means the level of the logging event should be left
    /// justified to a width of five characters.
    /// </para>
    /// <para>
    /// The recognized conversion pattern names are:
    /// </para>
    /// <list type="table">
    ///     <listheader>
    ///         <term>Conversion Pattern Name</term>
    ///         <description>Effect</description>
    ///     </listheader>
    ///     <item>
    ///         <term>a</term>
    ///         <description>Equivalent to <b>appdomain</b></description>
    ///     </item>
    ///     <item>
    ///         <term>appdomain</term>
    ///         <description>
    ///				Used to output the friendly name of the AppDomain where the 
    ///				logging event was generated. 
    ///         </description>
    ///     </item>
    ///     <item>
    ///         <term>c</term>
    ///         <description>Equivalent to <b>logger</b></description>
    ///     </item>
    ///     <item>
    ///         <term>C</term>
    ///         <description>Equivalent to <b>type</b></description>
    ///     </item>
    ///     <item>
    ///         <term>class</term>
    ///         <description>Equivalent to <b>type</b></description>
    ///     </item>
    ///     <item>
    ///         <term>d</term>
    ///         <description>Equivalent to <b>date</b></description>
    ///     </item>
    ///     <item>
    ///			<term>date</term> 
    ///			<description>
    /// 			<para>
    /// 			Used to output the date of the logging event in the local time zone. 
    /// 			To output the date in universal time use the <c>%utcdate</c> pattern.
    /// 			The date conversion 
    /// 			specifier may be followed by a <i>date format specifier</i> enclosed 
    /// 			between braces. For example, <b>%date{HH:mm:ss,fff}</b> or
    /// 			<b>%date{dd MMM yyyy HH:mm:ss,fff}</b>.  If no date format specifier is 
    /// 			given then ISO8601 format is
    /// 			assumed (<see cref="log4net.DateFormatter.Iso8601DateFormatter"/>).
    /// 			</para>
    /// 			<para>
    /// 			The date format specifier admits the same syntax as the
    /// 			time pattern string of the <see cref="DateTime.ToString(string)"/>.
    /// 			</para>
    /// 			<para>
    /// 			For better results it is recommended to use the log4net date
    /// 			formatters. These can be specified using one of the strings
    /// 			"ABSOLUTE", "DATE" and "ISO8601" for specifying 
    /// 			<see cref="log4net.DateFormatter.AbsoluteTimeDateFormatter"/>, 
    /// 			<see cref="log4net.DateFormatter.DateTimeDateFormatter"/> and respectively 
    /// 			<see cref="log4net.DateFormatter.Iso8601DateFormatter"/>. For example, 
    /// 			<b>%date{ISO8601}</b> or <b>%date{ABSOLUTE}</b>.
    /// 			</para>
    /// 			<para>
    /// 			These dedicated date formatters perform significantly
    /// 			better than <see cref="DateTime.ToString(string)"/>.
    /// 			</para>
    ///			</description>
    ///		</item>
    ///		<item>
    ///			<term>exception</term>
    ///			<description>
    ///				<para>
    ///				Used to output the exception passed in with the log message.
    ///				</para>
    ///				<para>
    /// 			If an exception object is stored in the logging event
    /// 			it will be rendered into the pattern output with a
    /// 			trailing newline.
    /// 			If there is no exception then nothing will be output
    /// 			and no trailing newline will be appended.
    /// 			It is typical to put a newline before the exception
    /// 			and to have the exception as the last data in the pattern.
    ///				</para>
    ///			</description>
    ///		</item>
    ///     <item>
    ///         <term>F</term>
    ///         <description>Equivalent to <b>file</b></description>
    ///     </item>
    ///		<item>
    ///			<term>file</term>
    ///			<description>
    ///				<para>
    ///				Used to output the file name where the logging request was
    ///				issued.
    ///				</para>
    ///				<para>
    ///				<b>WARNING</b> Generating caller location information is
    ///				extremely slow. Its use should be avoided unless execution speed
    ///				is not an issue.
    ///				</para>
    /// 			<para>
    /// 			See the note below on the availability of caller location information.
    /// 			</para>
    ///			</description>
    ///		</item>
    ///		<item>
    ///			<term>identity</term>
    ///			<description>
    ///				<para>
    ///				Used to output the user name for the currently active user
    ///				(Principal.Identity.Name).
    ///				</para>
    ///				<para>
    ///				<b>WARNING</b> Generating caller information is
    ///				extremely slow. Its use should be avoided unless execution speed
    ///				is not an issue.
    ///				</para>
    ///			</description>
    ///		</item>
    ///     <item>
    ///         <term>l</term>
    ///         <description>Equivalent to <b>location</b></description>
    ///     </item>
    ///     <item>
    ///         <term>L</term>
    ///         <description>Equivalent to <b>line</b></description>
    ///     </item>
    ///		<item>
    ///			<term>location</term>
    ///			<description>
    /// 			<para>
    /// 			Used to output location information of the caller which generated
    /// 			the logging event.
    /// 			</para>
    /// 			<para>
    /// 			The location information depends on the CLI implementation but
    /// 			usually consists of the fully qualified name of the calling
    /// 			method followed by the callers source the file name and line
    /// 			number between parentheses.
    /// 			</para>
    /// 			<para>
    /// 			The location information can be very useful. However, its
    /// 			generation is <b>extremely</b> slow. Its use should be avoided
    /// 			unless execution speed is not an issue.
    /// 			</para>
    /// 			<para>
    /// 			See the note below on the availability of caller location information.
    /// 			</para>
    ///			</description>
    ///		</item>
    ///		<item>
    ///			<term>level</term>
    ///			<description>
    /// 			<para>
    /// 			Used to output the level of the logging event.
    /// 			</para>
    ///			</description>
    ///		</item>
    ///		<item>
    ///			<term>line</term>
    ///			<description>
    ///				<para>
    ///				Used to output the line number from where the logging request
    ///				was issued.
    ///				</para>
    ///				<para>
    ///				<b>WARNING</b> Generating caller location information is
    ///				extremely slow. Its use should be avoided unless execution speed
    ///				is not an issue.
    ///				</para>
    /// 			<para>
    /// 			See the note below on the availability of caller location information.
    /// 			</para>
    ///			</description>
    ///		</item>
    ///     <item>
    ///         <term>logger</term>
    ///         <description>
    ///             <para>
    ///				Used to output the logger of the logging event. The
    /// 			logger conversion specifier can be optionally followed by
    /// 			<i>precision specifier</i>, that is a decimal constant in
    /// 			brackets.
    ///             </para>
    /// 			<para>
    /// 			If a precision specifier is given, then only the corresponding
    /// 			number of right most components of the logger name will be
    /// 			printed. By default the logger name is printed in full.
    /// 			</para>
    /// 			<para>
    /// 			For example, for the logger name "a.b.c" the pattern
    /// 			<b>%logger{2}</b> will output "b.c".
    /// 			</para>
    ///         </description>
    ///     </item>
    ///     <item>
    ///         <term>m</term>
    ///         <description>Equivalent to <b>message</b></description>
    ///     </item>
    ///     <item>
    ///         <term>M</term>
    ///         <description>Equivalent to <b>method</b></description>
    ///     </item>
    ///		<item>
    ///			<term>message</term>
    ///			<description>
    /// 			<para>
    /// 			Used to output the application supplied message associated with 
    /// 			the logging event.
    /// 			</para>
    ///			</description>
    ///		</item>
    ///		<item>
    ///			<term>mdc</term>
    ///			<description>
    /// 			<para>
    /// 			The MDC (old name for the ThreadContext.Properties) is now part of the
    /// 			combined event properties. This pattern is supported for compatibility
    /// 			but is equivalent to <b>property</b>.
    /// 			</para>
    ///			</description>
    ///		</item>
    ///		<item>
    ///			<term>method</term>
    ///			<description>
    ///				<para>
    ///				Used to output the method name where the logging request was
    ///				issued.
    ///				</para>
    ///				<para>
    ///				<b>WARNING</b> Generating caller location information is
    ///				extremely slow. Its use should be avoided unless execution speed
    ///				is not an issue.
    ///				</para>
    /// 			<para>
    /// 			See the note below on the availability of caller location information.
    /// 			</para>
    ///			</description>
    ///		</item>
    ///     <item>
    ///         <term>n</term>
    ///         <description>Equivalent to <b>newline</b></description>
    ///     </item>
    ///		<item>
    ///			<term>newline</term>
    ///			<description>
    /// 			<para>
    /// 			Outputs the platform dependent line separator character or
    /// 			characters.
    /// 			</para>
    /// 			<para>
    /// 			This conversion pattern offers the same performance as using 
    /// 			non-portable line separator strings such as	"\n", or "\r\n". 
    /// 			Thus, it is the preferred way of specifying a line separator.
    /// 			</para> 
    ///			</description>
    ///		</item>
    ///		<item>
    ///			<term>ndc</term>
    ///			<description>
    /// 			<para>
    /// 			Used to output the NDC (nested diagnostic context) associated
    /// 			with the thread that generated the logging event.
    /// 			</para>
    ///			</description>
    ///		</item>
    ///     <item>
    ///         <term>p</term>
    ///         <description>Equivalent to <b>level</b></description>
    ///     </item>
    ///     <item>
    ///         <term>P</term>
    ///         <description>Equivalent to <b>property</b></description>
    ///     </item>
    ///     <item>
    ///         <term>properties</term>
    ///         <description>Equivalent to <b>property</b></description>
    ///     </item>
    ///		<item>
    ///			<term>property</term>
    ///			<description>
    /// 			<para>
    /// 			Used to output the an event specific property. The key to 
    /// 			lookup must be specified within braces and directly following the
    /// 			pattern specifier, e.g. <b>%property{user}</b> would include the value
    /// 			from the property that is keyed by the string 'user'. Each property value
    /// 			that is to be included in the log must be specified separately.
    /// 			Properties are added to events by loggers or appenders. By default 
    /// 			the <c>log4net:HostName</c> property is set to the name of machine on 
    /// 			which the event was originally logged.
    /// 			</para>
    /// 			<para>
    /// 			If no key is specified, e.g. <b>%property</b> then all the keys and their
    /// 			values are printed in a comma separated list.
    /// 			</para>
    /// 			<para>
    /// 			The properties of an event are combined from a number of different
    /// 			contexts. These are listed below in the order in which they are searched.
    /// 			</para>
    /// 			<list type="definition">
    /// 				<item>
    /// 					<term>the event properties</term>
    /// 					<description>
    /// 					The event has <see cref="LoggingEvent.Properties"/> that can be set. These 
    /// 					properties are specific to this event only.
    /// 					</description>
    /// 				</item>
    /// 				<item>
    /// 					<term>the thread properties</term>
    /// 					<description>
    /// 					The <see cref="ThreadContext.Properties"/> that are set on the current
    /// 					thread. These properties are shared by all events logged on this thread.
    /// 					</description>
    /// 				</item>
    /// 				<item>
    /// 					<term>the global properties</term>
    /// 					<description>
    /// 					The <see cref="GlobalContext.Properties"/> that are set globally. These 
    /// 					properties are shared by all the threads in the AppDomain.
    /// 					</description>
    /// 				</item>
    /// 			</list>
    /// 			
    ///			</description>
    ///		</item>
    ///     <item>
    ///         <term>r</term>
    ///         <description>Equivalent to <b>timestamp</b></description>
    ///     </item>
    ///     <item>
    ///         <term>t</term>
    ///         <description>Equivalent to <b>thread</b></description>
    ///     </item>
    ///		<item>
    ///			<term>timestamp</term>
    ///			<description>
    /// 			<para>
    /// 			Used to output the number of milliseconds elapsed since the start
    /// 			of the application until the creation of the logging event.
    /// 			</para>
    ///			</description>
    ///		</item>
    ///		<item>
    ///			<term>thread</term>
    ///			<description>
    /// 			<para>
    /// 			Used to output the name of the thread that generated the
    /// 			logging event. Uses the thread number if no name is available.
    /// 			</para>
    ///			</description>
    ///		</item>
    ///     <item>
    ///			<term>type</term> 
    ///			<description>
    /// 			<para>
    /// 			Used to output the fully qualified type name of the caller
    /// 			issuing the logging request. This conversion specifier
    /// 			can be optionally followed by <i>precision specifier</i>, that
    /// 			is a decimal constant in brackets.
    /// 			</para>
    /// 			<para>
    /// 			If a precision specifier is given, then only the corresponding
    /// 			number of right most components of the class name will be
    /// 			printed. By default the class name is output in fully qualified form.
    /// 			</para>
    /// 			<para>
    /// 			For example, for the class name "log4net.Layout.PatternLayout", the
    /// 			pattern <b>%type{1}</b> will output "PatternLayout".
    /// 			</para>
    /// 			<para>
    /// 			<b>WARNING</b> Generating the caller class information is
    /// 			slow. Thus, its use should be avoided unless execution speed is
    /// 			not an issue.
    /// 			</para>
    /// 			<para>
    /// 			See the note below on the availability of caller location information.
    /// 			</para>
    ///			</description>
    ///     </item>
    ///     <item>
    ///         <term>u</term>
    ///         <description>Equivalent to <b>identity</b></description>
    ///     </item>
    ///		<item>
    ///			<term>username</term>
    ///			<description>
    ///				<para>
    ///				Used to output the WindowsIdentity for the currently
    ///				active user.
    ///				</para>
    ///				<para>
    ///				<b>WARNING</b> Generating caller WindowsIdentity information is
    ///				extremely slow. Its use should be avoided unless execution speed
    ///				is not an issue.
    ///				</para>
    ///			</description>
    ///		</item>
    ///     <item>
    ///			<term>utcdate</term> 
    ///			<description>
    /// 			<para>
    /// 			Used to output the date of the logging event in universal time. 
    /// 			The date conversion 
    /// 			specifier may be followed by a <i>date format specifier</i> enclosed 
    /// 			between braces. For example, <b>%utcdate{HH:mm:ss,fff}</b> or
    /// 			<b>%utcdate{dd MMM yyyy HH:mm:ss,fff}</b>.  If no date format specifier is 
    /// 			given then ISO8601 format is
    /// 			assumed (<see cref="log4net.DateFormatter.Iso8601DateFormatter"/>).
    /// 			</para>
    /// 			<para>
    /// 			The date format specifier admits the same syntax as the
    /// 			time pattern string of the <see cref="DateTime.ToString(string)"/>.
    /// 			</para>
    /// 			<para>
    /// 			For better results it is recommended to use the log4net date
    /// 			formatters. These can be specified using one of the strings
    /// 			"ABSOLUTE", "DATE" and "ISO8601" for specifying 
    /// 			<see cref="log4net.DateFormatter.AbsoluteTimeDateFormatter"/>, 
    /// 			<see cref="log4net.DateFormatter.DateTimeDateFormatter"/> and respectively 
    /// 			<see cref="log4net.DateFormatter.Iso8601DateFormatter"/>. For example, 
    /// 			<b>%utcdate{ISO8601}</b> or <b>%utcdate{ABSOLUTE}</b>.
    /// 			</para>
    /// 			<para>
    /// 			These dedicated date formatters perform significantly
    /// 			better than <see cref="DateTime.ToString(string)"/>.
    /// 			</para>
    ///			</description>
    ///		</item>
    ///     <item>
    ///         <term>w</term>
    ///         <description>Equivalent to <b>username</b></description>
    ///     </item>
    ///     <item>
    ///         <term>x</term>
    ///         <description>Equivalent to <b>ndc</b></description>
    ///     </item>
    ///     <item>
    ///         <term>X</term>
    ///         <description>Equivalent to <b>mdc</b></description>
    ///     </item>
    ///		<item>
    ///			<term>%</term>
    ///			<description>
    /// 			<para>
    /// 			The sequence %% outputs a single percent sign.
    /// 			</para>
    ///			</description>
    ///		</item>
    /// </list>
    /// <para>
    /// The single letter patterns are deprecated in favor of the 
    /// longer more descriptive pattern names.
    /// </para>
    /// <para>
    /// By default the relevant information is output as is. However,
    /// with the aid of format modifiers it is possible to change the
    /// minimum field width, the maximum field width and justification.
    /// </para>
    /// <para>
    /// The optional format modifier is placed between the percent sign
    /// and the conversion pattern name.
    /// </para>
    /// <para>
    /// The first optional format modifier is the <i>left justification
    /// flag</i> which is just the minus (-) character. Then comes the
    /// optional <i>minimum field width</i> modifier. This is a decimal
    /// constant that represents the minimum number of characters to
    /// output. If the data item requires fewer characters, it is padded on
    /// either the left or the right until the minimum width is
    /// reached. The default is to pad on the left (right justify) but you
    /// can specify right padding with the left justification flag. The
    /// padding character is space. If the data item is larger than the
    /// minimum field width, the field is expanded to accommodate the
    /// data. The value is never truncated.
    /// </para>
    /// <para>
    /// This behavior can be changed using the <i>maximum field
    /// width</i> modifier which is designated by a period followed by a
    /// decimal constant. If the data item is longer than the maximum
    /// field, then the extra characters are removed from the
    /// <i>beginning</i> of the data item and not from the end. For
    /// example, it the maximum field width is eight and the data item is
    /// ten characters long, then the first two characters of the data item
    /// are dropped. This behavior deviates from the printf function in C
    /// where truncation is done from the end.
    /// </para>
    /// <para>
    /// Below are various format modifier examples for the logger
    /// conversion specifier.
    /// </para>
    /// <div class="tablediv">
    ///		<table class="dtTABLE" cellspacing="0">
    ///			<tr>
    ///				<th>Format modifier</th>
    ///				<th>left justify</th>
    ///				<th>minimum width</th>
    ///				<th>maximum width</th>
    ///				<th>comment</th>
    ///			</tr>
    ///			<tr>
    ///				<td align="center">%20logger</td>
    ///				<td align="center">false</td>
    ///				<td align="center">20</td>
    ///				<td align="center">none</td>
    ///				<td>
    ///					<para>
    ///					Left pad with spaces if the logger name is less than 20
    ///					characters long.
    ///					</para>
    ///				</td>
    ///			</tr>
    ///			<tr>
    ///				<td align="center">%-20logger</td>
    ///				<td align="center">true</td>
    ///				<td align="center">20</td>
    ///				<td align="center">none</td>
    ///				<td>
    ///					<para>
    ///					Right pad with spaces if the logger 
    ///					name is less than 20 characters long.
    ///					</para>
    ///				</td>
    ///			</tr>
    ///			<tr>
    ///				<td align="center">%.30logger</td>
    ///				<td align="center">NA</td>
    ///				<td align="center">none</td>
    ///				<td align="center">30</td>
    ///				<td>
    ///					<para>
    ///					Truncate from the beginning if the logger 
    ///					name is longer than 30 characters.
    ///					</para>
    ///				</td>
    ///			</tr>
    ///			<tr>
    ///				<td align="center"><nobr>%20.30logger</nobr></td>
    ///				<td align="center">false</td>
    ///				<td align="center">20</td>
    ///				<td align="center">30</td>
    ///				<td>
    ///					<para>
    ///					Left pad with spaces if the logger name is shorter than 20
    ///					characters. However, if logger name is longer than 30 characters,
    ///					then truncate from the beginning.
    ///					</para>
    ///				</td>
    ///			</tr>
    ///			<tr>
    ///				<td align="center">%-20.30logger</td>
    ///				<td align="center">true</td>
    ///				<td align="center">20</td>
    ///				<td align="center">30</td>
    ///				<td>
    ///					<para>
    ///					Right pad with spaces if the logger name is shorter than 20
    ///					characters. However, if logger name is longer than 30 characters,
    ///					then truncate from the beginning.
    ///					</para>
    ///				</td>
    ///			</tr>
    ///		</table>
    ///	</div>
    ///	<para>
    ///	<b>Note about caller location information.</b><br />
    ///	The following patterns <c>%type %file %line %method %location %class %C %F %L %l %M</c> 
    ///	all generate caller location information.
    /// Location information uses the <c>System.Diagnostics.StackTrace</c> class to generate
    /// a call stack. The caller's information is then extracted from this stack.
    /// </para>
    /// <note type="caution">
    /// <para>
    /// The <c>System.Diagnostics.StackTrace</c> class is not supported on the 
    /// .NET Compact Framework 1.0 therefore caller location information is not
    /// available on that framework.
    /// </para>
    /// </note>
    /// <note type="caution">
    /// <para>
    /// The <c>System.Diagnostics.StackTrace</c> class has this to say about Release builds:
    /// </para>
    /// <para>
    /// "StackTrace information will be most informative with Debug build configurations. 
    /// By default, Debug builds include debug symbols, while Release builds do not. The 
    /// debug symbols contain most of the file, method name, line number, and column 
    /// information used in constructing StackFrame and StackTrace objects. StackTrace 
    /// might not report as many method calls as expected, due to code transformations 
    /// that occur during optimization."
    /// </para>
    /// <para>
    /// This means that in a Release build the caller information may be incomplete or may 
    /// not exist at all! Therefore caller location information cannot be relied upon in a Release build.
    /// </para>
    /// </note>
    /// <para>
    /// Additional pattern converters may be registered with a specific <see cref="PatternLayout"/>
    /// instance using the <see cref="AddConverter(string, Type)"/> method.
    /// </para>
    /// </remarks>
    /// <example>
    /// This is a more detailed pattern.
    /// <code><b>%timestamp [%thread] %level %logger %ndc - %message%newline</b></code>
    /// </example>
    /// <example>
    /// A similar pattern except that the relative time is
    /// right padded if less than 6 digits, thread name is right padded if
    /// less than 15 characters and truncated if longer and the logger
    /// name is left padded if shorter than 30 characters and truncated if
    /// longer.
    /// <code><b>%-6timestamp [%15.15thread] %-5level %30.30logger %ndc - %message%newline</b></code>
    /// </example>
    /// <author>Nicko Cadell</author>
    /// <author>Gert Driesen</author>
    /// <author>Douglas de la Torre</author>
    /// <author>Daniel Cazzulino</author>
    public class CustomLayout : log4net.Layout.LayoutSkeleton
    {
        #region Constants

        /// <summary>
        /// Default pattern string for log output. 
        /// </summary>
        /// <remarks>
        /// <para>
        /// Default pattern string for log output. 
        /// Currently set to the string <b>"%message%newline"</b> 
        /// which just prints the application supplied message. 
        /// </para>
        /// </remarks>
        public const string DefaultConversionPattern = "%message%newline";

        /// <summary>
        /// A detailed conversion pattern
        /// </summary>
        /// <remarks>
        /// <para>
        /// A conversion pattern which includes Time, Thread, Logger, and Nested Context.
        /// Current value is <b>%timestamp [%thread] %level %logger %ndc - %message%newline</b>.
        /// </para>
        /// </remarks>
        public const string DetailConversionPattern = "%timestamp [%thread] %level %logger %ndc - %message%newline";

        #endregion

        #region Static Fields

        /// <summary>
        /// Internal map of converter identifiers to converter types.
        /// </summary>
        /// <remarks>
        /// <para>
        /// This static map is overridden by the m_converterRegistry instance map
        /// </para>
        /// </remarks>
        private static Hashtable s_globalRulesRegistry;

        #endregion Static Fields

        #region Member Variables

        /// <summary>
        /// the pattern
        /// </summary>
        private string m_pattern;

        /// <summary>
        /// the head of the pattern converter chain
        /// </summary>
        private PatternConverter m_head;

        /// <summary>
        /// patterns defined on this PatternLayout only
        /// </summary>
        private Hashtable m_instanceRulesRegistry = new Hashtable();

        #endregion

        #region Static Constructor

        /// <summary>
        /// Initialize the global registry
        /// </summary>
        /// <remarks>
        /// <para>
        /// Defines the builtin global rules.
        /// </para>
        /// </remarks>
        static CustomLayout()
        {
            s_globalRulesRegistry = new Hashtable(8);
            s_globalRulesRegistry.Add("Message", typeof(MessagePatternConverter));
            s_globalRulesRegistry.Add("Source", typeof(SourcePatternConverter));
            s_globalRulesRegistry.Add("Form", typeof(FormPatternConverter));
            s_globalRulesRegistry.Add("QueryString", typeof(QueryStringPatternConverter));
            s_globalRulesRegistry.Add("TargetSite", typeof(TargetSitePatternConverter));
            s_globalRulesRegistry.Add("UserName", typeof(UserNamePatternConverter));
            s_globalRulesRegistry.Add("StackTrace", typeof(StackTracePatternConverter));
            s_globalRulesRegistry.Add("Solve", typeof(SolvePatternConverter));
        }

        #endregion Static Constructor

        #region Constructors

        /// <summary>
        /// Constructs a PatternLayout using the DefaultConversionPattern
        /// </summary>
        /// <remarks>
        /// <para>
        /// The default pattern just produces the application supplied message.
        /// </para>
        /// <para>
        /// Note to Inheritors: This constructor calls the virtual method
        /// <see cref="CreatePatternParser"/>. If you override this method be
        /// aware that it will be called before your is called constructor.
        /// </para>
        /// <para>
        /// As per the <see cref="IOptionHandler"/> contract the <see cref="ActivateOptions"/>
        /// method must be called after the properties on this object have been
        /// configured.
        /// </para>
        /// </remarks>
        public CustomLayout()
            : this(DefaultConversionPattern)
        {
        }

        /// <summary>
        /// Constructs a PatternLayout using the supplied conversion pattern
        /// </summary>
        /// <param name="pattern">the pattern to use</param>
        /// <remarks>
        /// <para>
        /// Note to Inheritors: This constructor calls the virtual method
        /// <see cref="CreatePatternParser"/>. If you override this method be
        /// aware that it will be called before your is called constructor.
        /// </para>
        /// <para>
        /// When using this constructor the <see cref="ActivateOptions"/> method 
        /// need not be called. This may not be the case when using a subclass.
        /// </para>
        /// </remarks>
        public CustomLayout(string pattern)
        {
            // By default we do not process the exception
            IgnoresException = true;

            m_pattern = pattern;
            if (m_pattern == null)
            {
                m_pattern = DefaultConversionPattern;
            }

            ActivateOptions();
        }

        #endregion

        /// <summary>
        /// The pattern formatting string
        /// </summary>
        /// <remarks>
        /// <para>
        /// The <b>ConversionPattern</b> option. This is the string which
        /// controls formatting and consists of a mix of literal content and
        /// conversion specifiers.
        /// </para>
        /// </remarks>
        public string ConversionPattern
        {
            get { return m_pattern; }
            set { m_pattern = value; }
        }

        /// <summary>
        /// Create the pattern parser instance
        /// </summary>
        /// <param name="pattern">the pattern to parse</param>
        /// <returns>The <see cref="PatternParser"/> that will format the event</returns>
        /// <remarks>
        /// <para>
        /// Creates the <see cref="PatternParser"/> used to parse the conversion string. Sets the
        /// global and instance rules on the <see cref="PatternParser"/>.
        /// </para>
        /// </remarks>
        virtual protected PatternParser CreatePatternParser(string pattern)
        {
            PatternParser patternParser = new PatternParser(pattern);

            // Add all the builtin patterns
            foreach (DictionaryEntry entry in s_globalRulesRegistry)
            {
                patternParser.PatternConverters[entry.Key] = entry.Value;
            }
            // Add the instance patterns
            foreach (DictionaryEntry entry in m_instanceRulesRegistry)
            {
                patternParser.PatternConverters[entry.Key] = entry.Value;
            }

            return patternParser;
        }

        #region Implementation of IOptionHandler

        /// <summary>
        /// Initialize layout options
        /// </summary>
        /// <remarks>
        /// <para>
        /// This is part of the <see cref="IOptionHandler"/> delayed object
        /// activation scheme. The <see cref="ActivateOptions"/> method must 
        /// be called on this object after the configuration properties have
        /// been set. Until <see cref="ActivateOptions"/> is called this
        /// object is in an undefined state and must not be used. 
        /// </para>
        /// <para>
        /// If any of the configuration properties are modified then 
        /// <see cref="ActivateOptions"/> must be called again.
        /// </para>
        /// </remarks>
        override public void ActivateOptions()
        {
            m_head = CreatePatternParser(m_pattern).Parse();

            PatternConverter curConverter = m_head;
            while (curConverter != null)
            {
                PatternLayoutConverter layoutConverter = curConverter as PatternLayoutConverter;
                if (layoutConverter != null)
                {
                    if (!layoutConverter.IgnoresException)
                    {
                        // Found converter that handles the exception
                        this.IgnoresException = false;

                        break;
                    }
                }
                curConverter = curConverter.Next;
            }
        }

        #endregion

        #region Override implementation of LayoutSkeleton

        /// <summary>
        /// Produces a formatted string as specified by the conversion pattern.
        /// </summary>
        /// <param name="loggingEvent">the event being logged</param>
        /// <param name="writer">The TextWriter to write the formatted event to</param>
        /// <remarks>
        /// <para>
        /// Parse the <see cref="LoggingEvent"/> using the patter format
        /// specified in the <see cref="ConversionPattern"/> property.
        /// </para>
        /// </remarks>
        override public void Format(TextWriter writer, LoggingEvent loggingEvent)
        {
            if (writer == null)
            {
                throw new ArgumentNullException("writer");
            }
            if (loggingEvent == null)
            {
                throw new ArgumentNullException("loggingEvent");
            }

            PatternConverter c = m_head;

            // loop through the chain of pattern converters
            while (c != null)
            {
                c.Format(writer, loggingEvent);
                c = c.Next;
            }
        }

        #endregion

        /// <summary>
        /// Add a converter to this PatternLayout
        /// </summary>
        /// <param name="converterInfo">the converter info</param>
        /// <remarks>
        /// <para>
        /// This version of the method is used by the configurator.
        /// Programmatic users should use the alternative <see cref="AddConverter(string,Type)"/> method.
        /// </para>
        /// </remarks>
        public void AddConverter(ConverterInfo converterInfo)
        {
            AddConverter(converterInfo.Name, converterInfo.Type);
        }

        /// <summary>
        /// Add a converter to this PatternLayout
        /// </summary>
        /// <param name="name">the name of the conversion pattern for this converter</param>
        /// <param name="type">the type of the converter</param>
        /// <remarks>
        /// <para>
        /// Add a named pattern converter to this instance. This
        /// converter will be used in the formatting of the event.
        /// This method must be called before <see cref="ActivateOptions"/>.
        /// </para>
        /// <para>
        /// The <paramref name="type"/> specified must extend the 
        /// <see cref="PatternConverter"/> type.
        /// </para>
        /// </remarks>
        public void AddConverter(string name, Type type)
        {
            if (name == null) throw new ArgumentNullException("name");
            if (type == null) throw new ArgumentNullException("type");

            if (!typeof(PatternConverter).IsAssignableFrom(type))
            {
                throw new ArgumentException("The converter type specified [" + type + "] must be a subclass of log4net.Util.PatternConverter", "type");
            }
            m_instanceRulesRegistry[name] = type;
        }

        /// <summary>
        /// Wrapper class used to map converter names to converter types
        /// </summary>
        /// <remarks>
        /// <para>
        /// Pattern converter info class used during configuration to
        /// pass to the <see cref="PatternLayout.AddConverter(ConverterInfo)"/>
        /// method.
        /// </para>
        /// </remarks>
        public sealed class ConverterInfo
        {
            private string m_name;
            private Type m_type;

            /// <summary>
            /// default constructor
            /// </summary>
            public ConverterInfo()
            {
            }

            /// <summary>
            /// Gets or sets the name of the conversion pattern
            /// </summary>
            /// <remarks>
            /// <para>
            /// The name of the pattern in the format string
            /// </para>
            /// </remarks>
            public string Name
            {
                get { return m_name; }
                set { m_name = value; }
            }

            /// <summary>
            /// Gets or sets the type of the converter
            /// </summary>
            /// <remarks>
            /// <para>
            /// The value specified must extend the 
            /// <see cref="PatternConverter"/> type.
            /// </para>
            /// </remarks>
            public Type Type
            {
                get { return m_type; }
                set { m_type = value; }
            }
        }
    }
}
